/* Copyright 2011 Tobias Marschall, Email: tm@cwi.nl 
 * 
 * This file is part of string-cover.
 *
 * string-cover is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * string-cover is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with string-cover.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "BranchAndBoundNode.h"

using namespace std;

BranchAndBoundNode::BranchAndBoundNode(const ProblemInstance& problem) : instance(problem), included(problem.getSubstrings().size()), forbidden(problem.getSubstrings().size()), multipliers(0) {
	this->priority = 0.0;
	this->is_root = true;
}

BranchAndBoundNode::BranchAndBoundNode(const BranchAndBoundNode& node) : priority(node.priority), instance(node.instance), included(node.included), forbidden(node.forbidden), multipliers(0) {
	this->is_root = false;
	if (node.multipliers!=0) {
		this->multipliers = new Multipliers(*node.multipliers);
	}
}

BranchAndBoundNode::~BranchAndBoundNode() {
	// cout << "Destroying node " << this << endl;
	if (multipliers!=0) delete multipliers;
}

double BranchAndBoundNode::getPriority() const {
    return priority;
}


void BranchAndBoundNode::setPriority(double priority) {
    this->priority = priority;
}

void BranchAndBoundNode::forbidSubstring(size_t substring_index) {
	assert(substring_index < forbidden.size());
	forbidden.set(substring_index);
}

const ProblemInstance & BranchAndBoundNode::getProblemInstance() const {
	return instance;
}

void BranchAndBoundNode::includeSubstring(size_t substring_index) {
	assert(substring_index < included.size());
	included.set(substring_index);
}

bool BranchAndBoundNode::isForbidden(size_t substring_index) const {
	assert(substring_index < forbidden.size());
	return forbidden[substring_index];
}



bool BranchAndBoundNode::isIncluded(size_t substring_index) const {
	assert(substring_index < included.size());
	return included[substring_index];
}

double BranchAndBoundNode::weightOfIncluded() const {
	// TODO: cache result?
	double result = 0.0;
	for (size_t i = included.find_first(); i!=boost::dynamic_bitset<>::npos; i=included.find_next(i)) {
		result += instance.getWeight(i);
	}
	return result;
}

const Multipliers* BranchAndBoundNode::getMultipliers() const {
	return multipliers;
}

void BranchAndBoundNode::setMultipliers(auto_ptr<Multipliers> multipliers) {
	if (this->multipliers!=0) delete this->multipliers;
	this->multipliers = multipliers.release();
}

const ProblemInstance & BranchAndBoundNode::getInstance() const {
	return instance;
}

bool BranchAndBoundNode::isRoot() const
{
    return is_root;
}

std::ostream & operator<<(std::ostream& os, const BranchAndBoundNode & node) {
	const SubstringStore& substrings = node.instance.getSubstrings();
	os << "[Included: {";
	size_t n = 0;
	for (size_t i = node.included.find_first(); i!=boost::dynamic_bitset<>::npos; i=node.included.find_next(i)) {
		if (n++>0) os << ",";
		os << substrings.getSubstring(i);
	}
	os << "}, forbidden: {";
	n = 0;
	for (size_t i = node.forbidden.find_first(); i!=boost::dynamic_bitset<>::npos; i=node.forbidden.find_next(i)) {
		if (n++>0) os << ",";
		os << substrings.getSubstring(i);
	}
	os << "}, priority: " << node.priority << "]";
	return os;
}


